/**
 * @(#) RobotSimulator.java
 */

package pcsr.drivers.simulatorDriver;


import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;

import pcsr.Debug;
import pcsr.hwVirtualization.Actuator;
import pcsr.hwVirtualization.ActuatorMode;
import pcsr.hwVirtualization.ActuatorValue;
import pcsr.hwVirtualization.IRobotDriverObservable;
import pcsr.hwVirtualization.IRobotDriverObserver;
import pcsr.hwVirtualization.RobotInfo;
import pcsr.hwVirtualization.Sensor;
import pcsr.hwVirtualization.SensorMode;
import pcsr.hwVirtualization.SensorValue;
import pcsr.simulator.control.ISimulatorActions;
import pcsr.simulator.control.ISimulatorObservable;
import pcsr.simulator.control.ISimulatorObserver;
import pcsr.simulator.control.RobotBrain;
import pcsr.simulator.ui.SimulatorUIFrame;


public class RobotSimulatorDriver implements IRobotDriverObservable, ISimulatorObserver
{
	private static final int SensorMaxValue = 30;
	private static final int ActuatorMaxValue = 20;

	private Hashtable<String,SimulatorActuator> actuators;

	private List<IRobotDriverObserver> robotobservers = new LinkedList<IRobotDriverObserver>();

	private Hashtable<String,SimulatorSensor> sensors;

	private ISimulatorActions simulator;

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Collection<Actuator> GetAllActuators() {
		Collection<Actuator> ret = new LinkedList<Actuator>();

		for(SimulatorActuator na : actuators.values())
		{
			Actuator a = TranslateActuator(na);
			ret.add(a);
		}
		return ret;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Collection<Sensor> GetAllSensors() {
		Collection<Sensor> ret = new LinkedList<Sensor>();

		for(SimulatorSensor ns : sensors.values())
		{
			Sensor s = TranslateSensor(ns);
			ret.add(s);
		}
		return ret;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public RobotInfo GetRobotInfo() {
		RobotInfo ret = new RobotInfo();
		ret.SetName("PCSR Robot Simulator");
		return ret;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void NotifySimulatorActuatorValue(String actuatorID, double actuatorValue) {
		// TODO Auto-generated method stub
		SimulatorActuator sa = actuators.get(actuatorID);
		if(sa != null)
		{
			sa.SetActuatorValue(actuatorValue);
			for(IRobotDriverObserver rdo : robotobservers)
			{
				rdo.ActuatorChanged(TranslateActuator(sa));
			}
		}

	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void NotifySimulatorSensorValue(String sensorID, double sensorValue) {
		// TODO Auto-generated method stub
		SimulatorSensor ss = sensors.get(sensorID);
		if(ss != null)
		{
			ss.SetSensorValue(sensorValue);
			for(IRobotDriverObserver rdo : robotobservers)
			{
				rdo.SensorChanged(TranslateSensor(ss));
			}
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void ObserverRobotDriver(IRobotDriverObserver observer) {
		robotobservers.add(observer);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void SetActuatorStatus(Actuator actuator) {
		SimulatorActuator theSimulatorActuator = actuators.get(actuator.GetActuatorID());
		if(theSimulatorActuator != null)
		{	
			if(Debug.DEBUG)
			{
				System.err.print(actuator.GetActuatorID() + "--> ")	;
			}
			theSimulatorActuator.SetActuatorValue(actuator.GetActuatorValue().GetUnnormalizedValue());

			simulator.SetSimulatorActuatorValue(theSimulatorActuator.GetActuatorID(), theSimulatorActuator.GetActuatorValue());
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void SetSensorStatus(Sensor sensor) {
		SimulatorSensor theSimulatorSensor = sensors.get(sensor.GetSensorID());
		if(theSimulatorSensor != null)
		{			
			theSimulatorSensor.SetSensorValue(sensor.GetSensorValue().GetUnnormalizedValue());

			simulator.SetSimulatorSensorValue(theSimulatorSensor.GetSensorID(), theSimulatorSensor.GetSensorValue());
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void UnObserveRobotDriver(IRobotDriverObserver observer) {
		robotobservers.add(observer);
	}

	
	private void InitializeInternal() {
		simulator = RobotBrain.GetInstance();

		for(SimulatorActuator sa : simulator.GetAllActuators())
		{
			actuators.put(sa.GetActuatorID(), sa);
		}
		for (SimulatorSensor ss : simulator.GetAllSensors()) 
		{
			sensors.put(ss.GetSensorID(), ss);
		}

		((ISimulatorObservable)simulator).ObserveSimulator(this);

		SimulatorUIFrame.LaunchSimulatorUI();


		simulator.Start();
	}
	
	/**
	 * {@inheritDoc}
	 */
	public void Initialize() {	}

	private Actuator TranslateActuator(SimulatorActuator na) {
		Actuator a = new Actuator(na.GetActuatorID());	

		ActuatorValue av = new ActuatorValue(ActuatorMaxValue);
		double avv = na.GetActuatorValue();
		av.SetUnnormalizedValue(avv);
		a.SetValue(av);

		ActuatorMode am = new ActuatorMode();		
		ArrayList<String> availModes = new ArrayList<String>();
		for(String smode : availModes)
		{
			availModes.add(smode);
		}

		am.SetAvailableModes(availModes);		
		am.SetSelectedMode(na.GetActuatorMode());
		a.SetMode(am);

		return a;
	}

	private Sensor TranslateSensor(SimulatorSensor ns) {
		Sensor s = new Sensor(ns.GetSensorID());

		SensorMode sm = new SensorMode();		
		ArrayList<String> availModes = new ArrayList<String>();
		for(String smode : availModes)
		{
			availModes.add(smode);
		}

		sm.SetAvailableModes(availModes);
		sm.SetSelectedMode(ns.GetSensorMode());	
		s.SetMode(sm);

		SensorValue sv = new SensorValue(SensorMaxValue);
		double svv = ns.GetSensorValue();
		sv.SetUnnormalizedValue(svv);
		s.SetValue(sv);

		return s;
	}

	{
		actuators = new Hashtable<String, SimulatorActuator>();
		sensors = new Hashtable<String, SimulatorSensor>();
		InitializeInternal();
	}

}
